﻿using System.IO;
using SharpDX.XAudio2;
using SharpDX.Multimedia;
using System;
using SharpDX.IO;

namespace OpenGameEngine.Audio
{
    /// <summary>
    /// The AudioPlayer
    /// </summary>
    public class AudioPlayer
    {
        /// <summary>
        /// Gets the current volume of the audio player
        /// </summary>
        public float Volume { get { return _sourceVoice.Volume; } }
        private SourceVoice _sourceVoice;
        private AudioBufferAndMetaData _buffer;

        internal AudioPlayer(XAudio2 engine, Stream fileStream)
        {
            _buffer = GetBuffer(fileStream);
            _sourceVoice = new SourceVoice(engine, _buffer.WaveFormat, VoiceFlags.None, true);
        }

        private AudioBufferAndMetaData GetBuffer(Stream fileStream)
        {
            SoundStream soundstream = new SoundStream(fileStream);

            return new AudioBufferAndMetaData()
            {
                Stream = soundstream.ToDataStream(),
                AudioBytes = (int)soundstream.Length,
                Flags = BufferFlags.EndOfStream,
                WaveFormat = soundstream.Format,
                DecodedPacketsInfo = soundstream.DecodedPacketsInfo,
            };
        }

        /// <summary>
        /// Sets the volume for the audio player
        /// </summary>
        /// <param name="volume">the volume (0.0f - 1.0f)</param>
        public void SetVolume(float volume)
        {
            _sourceVoice.SetVolume(volume, XAudio2.CommitNow);
        }

        /// <summary>
        /// Plays the audio fragment
        /// </summary>
        public void Start()
        {
            _sourceVoice.SubmitSourceBuffer(_buffer, _buffer.DecodedPacketsInfo);
            _sourceVoice.Start();
        }

        /// <summary>
        /// Stops the audio fragment
        /// </summary>
        public void Stop()
        {
            _sourceVoice.FlushSourceBuffers();
            _sourceVoice.Stop();
        }

        private sealed class AudioBufferAndMetaData : AudioBuffer
        {
            public WaveFormat WaveFormat { get; set; }
            public uint[] DecodedPacketsInfo { get; set; }
        }
    }
}
